<template>
    <!-- <remote-script src="https://pv.sohu.com/cityjson?ie=utf-8"></remote-script> -->
    <el-row class="lucidity-editor-toolbar box-bottom-shadow">
        <el-col :span="12" class="lucidity-editor-toolbar-title">
            <span class="toolbar-path-info-icon"> 
                <i class="toolbar-op-icon fa fa-terminal"></i>
            </span>
            <span class="toolbar-path-info" :title="path">{{path}}</span>
        </el-col>

        <el-col :span="12" class="lucidity-editor-toolbar-common">
            <span v-if="mode === 'markdown'" class="markdown-op-icon">
                <i class="toolbar-op-icon fa fa-header" @click="headerClickHandler"></i>
                <i class="toolbar-op-icon fa fa-bold" @click="boldClickHandler"></i>
                <i class="toolbar-op-icon fa fa-italic" @click="italicClickHandler"></i>
                <i class="toolbar-op-icon fa fa-strikethrough" @click="strikethroughClickHandler"></i>

                <i class="toolbar-op-icon fa fa-quote-right" @click="quoteClickHandler"></i>
                <i class="toolbar-op-icon fa fa-list-ol" @click="orderListClickHandler"></i>
                <i class="toolbar-op-icon fa fa-list-ul" @click="disorderClickHandler"></i>

                <i class="toolbar-op-icon fa fa-code" @click="codeClickHandler"></i>
                <i class="toolbar-op-icon fa fa-table" @click="tableClickHandler"></i>
                <i class="toolbar-op-icon fa fa-chain" @click="chainClickHandler"></i>
                <i class="toolbar-op-icon fa fa-picture-o" @click="imageClickHandler"></i>

                <i class="toolbar-op-icon fa fa-eye-slash" @click="previewClickHandler" v-if="isEditMode"></i>  <!-- 编辑模式 -->
                <i class="toolbar-op-icon fa fa-eye" @click="previewClickHandler" v-else></i> <!-- 预览模式 -->
            </span>

            <!-- <el-icon class="toolbar-op-icon"><ArrowLeft /></el-icon> -->
            <!-- <el-icon class="toolbar-op-icon"><ArrowRight /></el-icon> -->
            <!-- 信息查看模式 -->
            <!-- <el-icon class="toolbar-op-icon"><DataAnalysis /></el-icon> -->
            <!-- 阅读模式 -->
            <!-- <el-icon class="toolbar-op-icon"><Reading /></el-icon> -->
            <!-- 编辑模式 -->
            <!-- <el-icon class="toolbar-op-icon"><Edit /></el-icon> -->
            <!-- 执行代码 -->
            <!-- <el-icon class="toolbar-op-icon"><Monitor /></el-icon> -->
            <!-- 复制文档内容 -->
            <!-- <el-icon class="toolbar-op-icon"><CopyDocument /></el-icon> -->
            <!-- 复制文档内容 -->
            <el-icon class="toolbar-op-icon" @click="save"><i class="fa fa-floppy-o" aria-hidden="true"></i></el-icon>
        </el-col>
    </el-row>

    <!-- 主要内容区域 -->
    <el-row class="lucidity-note-editor-box box-bottom-shadow">
        <el-col :span="previewWidth" class="preview-box" v-if="isShowPreview">
            <div class="preview-box-content" id="preview-content"></div>
        </el-col>
        <el-col :span="editboxWidth" class="edit-box">
            <textarea name="editor" id="editor" style="display:none"></textarea>
        </el-col>
    </el-row>
</template>

<script scope>
    import {ref, reactive, toRefs, onMounted, shallowRef, markRaw} from "vue";

    export default ({
        props: ['transfer'],

        setup(props, {emit}) {
            const LUCIDITY_NOTE_EDITOR_DATASET = reactive({
                editor: null,
                path: props.transfer.path,
                isShowPreview: props.transfer.isShowPreview,
                editboxWidth: props.transfer.editboxWidth,
                previewWidth: props.transfer.previewWidth,
                previewDelayTime: 300,
                previewDelay: null,
                mode: props.transfer.mode,
                isEditMode: true
            });

            const save = () => {
                var content = LUCIDITY_NOTE_EDITOR_DATASET.editor.getValue();
                LucidityNoteApp.Helper.net.put(
                    "/notetree/update/content",
                    {path: LUCIDITY_NOTE_EDITOR_DATASET.path, content: content},
                    (response) => {
                        ElementPlus.ElMessage({
                            type: "success",
                            message: response.message
                        })
                    },
                    (err) => {ElementPlus.ElMessage.error(err.message)}
                );
            };

            /**
             * 预览处理
             * @param {*} previewText 
             */
            const preview = (previewText) => {
                var options = {
                    async: false,
                    baseUrl: null,
                    breaks: true,
                    extensions: null,
                    gfm: true,
                    headerIds: true,
                    headerPrefix: "",
                    highlight: (code) => hljs.highlightAuto(code).value,
                    langPrefix: "language-",
                    mangle: true,
                    pedantic: false,
                    renderer: new marked.Renderer(),
                    sanitize: false,
                    sanitizer: null,
                    silent: false,
                    smartypants: false,
                    tokenizer: null,
                    walkTokens: null,
                    xhtml: false
                };
                var lexed = marked.lexer(previewText, options);
                var content = marked.parser(lexed, options);
                document.getElementById('preview-content').innerHTML = content;
            };

            /**
             * 标题点击事件
             */
            const headerClickHandler = () => {
                dealFontType("#### ", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 粗体点击事件
             */
            const boldClickHandler = () => {
                dealFontType("****", LUCIDITY_NOTE_EDITOR_DATASET.editor, true)
            };
            
            /**
             * 斜体点击事件
             */
            const italicClickHandler = () => {
                dealFontType("**", LUCIDITY_NOTE_EDITOR_DATASET.editor, true)
            };

            /**
             * 删除线点击事件
             */
            const strikethroughClickHandler = () => {
                dealFontType("~~~~", LUCIDITY_NOTE_EDITOR_DATASET.editor, true)
            };

            /**
             * 引用点击事件
             */
            const quoteClickHandler = () => {
                dealFontType("> ", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 有序列表点击事件
             */
            const orderListClickHandler = () => {
                dealFontType("1. ", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 无序列表点击事件
             */
            const disorderClickHandler = () => {
                dealFontType("- ", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 代码块点击事件
             */
            const codeClickHandler = () => {
                dealFontType("```[请输入代码类型]\r\n```", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 表格点击事件
             */
            const tableClickHandler = () => {
                dealFontType("|  表头   | 表头  |\r\n|  ----  | ----  |\r\n| 单元格  | 单元格 |", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 链接点击事件
             */
            const chainClickHandler = () => {
                dealFontType("[链接名称](链接地址)", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 图片点击事件
             */
            const imageClickHandler = () => {
                dealFontType("![图片名称](图片地址)", LUCIDITY_NOTE_EDITOR_DATASET.editor, false, true)
            };

            /**
             * 预览点击事件
             */
            const previewClickHandler = () => {
                LUCIDITY_NOTE_EDITOR_DATASET.isEditMode = !LUCIDITY_NOTE_EDITOR_DATASET.isEditMode
                if (LUCIDITY_NOTE_EDITOR_DATASET.isEditMode && LUCIDITY_NOTE_EDITOR_DATASET.isShowPreview) {
                    LUCIDITY_NOTE_EDITOR_DATASET.editboxWidth = 12;
                    LUCIDITY_NOTE_EDITOR_DATASET.previewWidth = 12;
                } else if (!LUCIDITY_NOTE_EDITOR_DATASET.isEditMode && LUCIDITY_NOTE_EDITOR_DATASET.isShowPreview) {
                    LUCIDITY_NOTE_EDITOR_DATASET.editboxWidth = 0;
                    LUCIDITY_NOTE_EDITOR_DATASET.previewWidth = 24;
                }
            };

            const dealFontType = (typeStr, editor, isSelectOp, isOriginLen) => {
                const cursor = editor.getCursor()
                const { line: curLine, ch: curPos } = cursor;
                if (isSelectOp && editor.somethingSelected()) {
                    const selectContent = editor.listSelections()[0]
                    let { anchor, head } = selectContent;      // 前后光标位置
                    [head, anchor] = [anchor, head];
                    let { line: preLine, ch: prePos } = head   // 往前匹配字符
                    let { line: aftLine, ch: aftPos } = anchor // 往后匹配字符

                    // 匹配字符
                    let matchStr = typeStr.substring(0, typeStr.length / 2)
                    const preText = editor.getRange({ line: preLine, ch: prePos - typeStr.length / 2}, head)    
                    const lastText = editor.getRange(anchor, { line: aftLine, ch: aftPos + typeStr.length / 2})

                    // 判断选中的文字前后是否包含需要匹配的字符串
                    let isBeforeMatch = preText === matchStr
                    let isAfterMatch = lastText === matchStr
                    let changePos = matchStr.length;
                    if (!isBeforeMatch && !isAfterMatch) { // 前后都没有匹配到对应的字符
                        editor.setCursor(anchor)
                        editor.replaceSelection(matchStr)
                        editor.setCursor(head)
                        editor.replaceSelection(matchStr)
                        prePos += changePos
                        aftPos += aftLine === preLine ? changePos : 0
                        editor.setSelection(
                            { line: aftLine, ch: aftPos },
                            { line: preLine, ch: prePos }
                        )
                    }
                } else {
                    editor.replaceSelection(typeStr);
                    editor.setCursor({ line: curLine, ch: isOriginLen ? (curPos + typeStr.length) : (curPos + typeStr.length / 2)});
                }
                editor.focus();
            };

            onMounted(() => {
                // 记: 新建 CodeMirror 时使用markRaw标记后绑定要Vue组件。但是创建 CodeMirror 对象不需要被vue追踪。
                // 不使用 markRaw 标记后绑定将出现光标错乱和无法展示
                LUCIDITY_NOTE_EDITOR_DATASET.editor = markRaw(CodeMirror.fromTextArea(document.getElementById("editor"), {
                    lineNumbers: true,        // 是否在编辑器左侧显示行号
                    matchBrackets: true,      // 括号匹配
                    mode: props.transfer.mime,    
                    indentUnit: 4,             // 缩进单位为4
                    indentWithTabs: true,     //
                    smartIndent: true,        // 自动缩进，设置是否根据上下文自动缩进（和上一行相同的缩进量）。默认为true。
                    styleActiveLine: true,    // 当前行背景高亮
                    theme: props.transfer.theme, // 编辑器主题
                    lineWrapping: true,      // 自动换行
                    matchBrackets: true,     // 括号匹配显示
                    autoCloseBrackets: true, // 输入和退格时成对
                    autoRefresh: true,       // 自动刷新
                    lint: true,
                    foldGutter: true,
                    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                    autoCloseBrackets: true, // 关闭自动补全括号之类的符号
                    autoCloseTags: true, // 关闭自动补全标记
                    extraKeys: {
                        // 保存快捷键设置
                        "Ctrl-S": function() {save();},
                        "Alt-F": "findPersistent"
                    }
                }));
        
                LUCIDITY_NOTE_EDITOR_DATASET.editor.setValue(props.transfer.content); 

                LUCIDITY_NOTE_EDITOR_DATASET.editor.on("change", () => {
                    clearTimeout(LUCIDITY_NOTE_EDITOR_DATASET.previewDelay);
                    LUCIDITY_NOTE_EDITOR_DATASET.previewDelay = setTimeout(() => {
                        preview(LUCIDITY_NOTE_EDITOR_DATASET.editor.getValue())
                    }, LUCIDITY_NOTE_EDITOR_DATASET.previewDelayTime);
                });

                // 如果是进行预览并且为 markdown 的时候
                if (props.transfer.isShowPreview && props.transfer.mode === "markdown") {
                    preview(props.transfer.content)
                }
            });

            return {
                ...toRefs(LUCIDITY_NOTE_EDITOR_DATASET),
                headerClickHandler,
                boldClickHandler,
                italicClickHandler,
                strikethroughClickHandler,
                quoteClickHandler,
                orderListClickHandler,
                disorderClickHandler,
                codeClickHandler,
                tableClickHandler,
                chainClickHandler,
                imageClickHandler,
                previewClickHandler,
                save
            }
        }
    })
</script>

<style scoped>
    .lucidity-editor-toolbar {
        height: 2rem;
        width: var(--lucidity-note-full-width);
        border-radius: 2rem;
        background: var(--lucidity-note-common-liner-gradient);
    }

    .lucidity-editor-toolbar-common {
        padding-right: 1rem;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        font-size: 0.9rem;
    }

    .toolbar-path-info {
        padding-left: .5rem;
        font-size: .9rem;
    }

    .lucidity-editor-toolbar-title {
        line-height: 2rem;
        padding-left: .3rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .toolbar-op-icon {
        padding-left: .5rem;
        cursor: pointer;
    }

    .lucidity-note-editor-box {
        height: calc(var(--lucidity-note-full-height) - 2.5rem);
        width: var(--lucidity-note-full-width);
        margin: .5rem 0rem 0rem 0rem;
        background: var(--lucidity-note-common-liner-gradient);
        font-size: var(--lucidity-note-editor-font-size);
        border-radius: 3px;
    }

    .toolbar-op-icon:hover {
        color: var(--lucidity-note-common-hover-color);
    }

    .edit-box {
        height: 100%;
        overflow-y: auto;
    }

    .preview-box {
        height: 100%;
        overflow-y: auto;
        padding: 1rem;
        background-color: var(--lucidity-note-app-preview-bk);
    }

    .markdown-op-icon, .toolbar-path-info-icon {
        height: 1em;
        width: auto;
        line-height: 1em;
        display: inline-flex;
        justify-content: center;
        align-items: center;
        position: relative;
        fill: currentColor;
        color: var(--lucidity-note-font-color);
        /* font-size: inherit; */
        font-weight: lighter;
        /* padding-right: 1rem; */
    }
</style>

<style>
    
    /** 预览高亮样式 */
    /** 标题样式 */
    .preview-box-content h1::before,
    .preview-box-content h2::before,
    .preview-box-content h3::before,
    .preview-box-content h4::before,
    .preview-box-content h5::before,
    .preview-box-content h6::before {
        font-weight: 600;
        top: 0;
        left: -15px;
        color: var(--lucidity-note-app-h-color);
        content: "#";
        padding-right: 10px;
    }

    .preview-box-content h1,
    .preview-box-content h2,
    .preview-box-content h3,
    .preview-box-content h4,
    .preview-box-content h5,
    .preview-box-content h6 {
        margin: .5rem 0rem;
    }
    
    .preview-box-content h1 {
        font-size: 1.8rem;
    }

    .preview-box-content h2 {
        font-size: 1.6rem;

    }

    .preview-box-content h3 {
        font-size: 1.4rem;
    }

    .preview-box-content h4 {
        font-size: 1.2rem;
    }

    .preview-box-content h5 {
        font-size: 1rem;
    }

    .preview-box-content h6 {
        font-size: .8rem;
    }

    /** ..
     */
    .preview-box-content blockquote{
        -moz-box-shadow: var(--lucidity-note-app-blockquote-shadow);
        -webkit-box-shadow: var(--lucidity-note-app-blockquote-shadow);
        box-shadow: var(--lucidity-note-app-blockquote-shadow);
        /* border-radius: .5rem; */
        background-color: var(--lucidity-note-app-blockquote-bk);
        border-left: var(--lucidity-note-app-blockquote);
        margin: 1rem 1.5rem;
        padding: .5rem 1rem;
    }

    .preview-box-content blockquote > p {
        display: inline;
    }

    .preview-box-content blockquote::before{
    }

    .preview-box-content blockquote::after{}

    /** 预览 Table 表格样式 */
    .preview-box-content table {
        border: 1px;
        width: 95%;
        background: var(--lucidity-note-app-table-bk);
        margin: 10px auto;
        border-collapse: collapse;
    }

    .preview-box-content table > thead > tr > th {
        height: 25px;
        line-height: 25px;
        text-align: center;
        border: var(--lucidity-note-app-preview-border);
        background: var(--lucidity-note-app-table-thread-bk);
    }

    .preview-box-content table > tbody > tr > td {
        height: 25px;
        line-height: 25px;
        text-align: center;
        border: var(--lucidity-note-app-preview-border);
        background: var(--lucidity-note-app-table-tbody-bk);
    }

    /** 代码框样式 */
    .preview-box-content pre {
        border: var(--lucidity-note-app-preview-border);
        padding: .5rem;
        border-radius: .3rem;
    }

    .preview-box-content pre > code {
        width: 100%;
        height: 100%;
        word-break: break-all;
        white-space: pre-wrap;
    }

    .preview-box-content p > img {
        width: 100%;
    }

</style>

<style>
    .lucidity-note-editor-box .CodeMirror {
        width: var(--lucidity-note-full-width);
        height: var(--lucidity-note-full-height);
        background: transparent;
    }

    .lucidity-note-editor-box .CodeMirror > div > textarea {
        position: absolute !important;
        width: 30px !important;
        height: 30px !important;
        top: 29px !important;
        left: 55px !important;
        z-index: 1000 !important;
        background: transparent !important;
        border-width: 0px !important;
        outline: none !important;
        overflow: hidden !important;
        opacity: 0.05;
    }

    .lucidity-note-editor-box .CodeMirror-scroll {
        margin-right: 0px !important;
        padding-bottom: 0px !important;
        overflow-x: hidden !important;
    }

    .lucidity-note-editor-box .CodeMirror-dialog-top {
        background: var(--lucidity-note-codemirror-search-bk);
    }
</style>